﻿using Elastic.Clients.Elasticsearch;
using Microsoft.AspNetCore.Mvc;

namespace Cordyceps.Tool.ES.Demo.Controllers;

[ApiController]
[Route("api/data")]
public class DataController : ControllerBase
{
    private const string IndexName = "t_book";
    private readonly ElasticsearchClient _elasticsearchClient;


    public DataController(ElasticsearchClient elasticsearchClient)
    {
        _elasticsearchClient = elasticsearchClient;
    }


    #region 01-单个新增文档

    /// <summary>
    ///     01-单个新增文档
    /// </summary>
    /// <param name="book"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [Route("add_book")]
    [HttpPost]
    public async Task<string> AddBookAsync(Book book)
    {
        //https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/getting-started#_getting_documents
        var response = await _elasticsearchClient.IndexAsync(book, x => x.Index(IndexName)); //官方写法

        //var response = await _elasticsearchClient.IndexAsync(book);   //这种写法必须初始化连接的时候打开.DefaultIndex("t_book"),显然不灵活
        if (!response.IsValidResponse)
            throw new Exception($"添加文档失败: {response.DebugInformation}");

        return response.Id;
    }

    #endregion

    #region 02-批量新增文档

    /// <summary>
    ///     02-批量新增文档
    /// </summary>
    /// <param name="books"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [Route("bulk_add_book")]
    [HttpPost]
    public async Task BulkAddBooksAsync(IEnumerable<Book> books)
    {
        var response = await _elasticsearchClient.IndexManyAsync(books, IndexName);

        if (!response.IsValidResponse)
        {
            var errors = response.Items
                .Where(item => !item.IsValid)
                .Select(item => $"文档 {item.Id}: {item.Error?.Reason}")
                .ToList();

            throw new Exception($"批量添加失败: {string.Join("\n", errors)}");
        }
    }

    #endregion

    #region 03-删除文档

    /// <summary>
    ///     03-删除文档
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [Route("delete_book")]
    [HttpPost]
    public async Task<bool> DeleteBookAsync(string id)
    {
        var response = await _elasticsearchClient.DeleteAsync<Book>(IndexName, id);
        return response.IsSuccess();
    }

    #endregion

    #region 04-更新文档

    /// <summary>
    ///     04-更新文档
    /// </summary>
    /// <param name="book"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [Route("update_book")]
    [HttpPost]
    public async Task UpdateBookAsync(Book book)
    {
        var response = await _elasticsearchClient.UpdateAsync<Book, Book>(IndexName, book.Id, u => u.Doc(book));
        if (!response.IsValidResponse)
            throw new Exception($"更新失败: {response.DebugInformation}");
    }

    #endregion

    #region 05-根据ID查询文档

    /// <summary>
    ///     05-根据ID查询文档
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [Route("get_book")]
    [HttpPost]
    public async Task<Book> GetBookByIdAsync(string id)
    {
        var response = await _elasticsearchClient.GetAsync<Book>(id, idx => idx.Index(IndexName));
        if (!response.IsValidResponse || !response.Found)
            return null;
        return response.Source;
    }

    #endregion
}

public class Book
{
    public int Id { get; set; }

    /// <summary>
    ///     UserAgent
    /// </summary>
    public string UserAgent { get; set; }

    /// <summary>
    ///     Method
    /// </summary>
    public string Method { get; set; }

    /// <summary>
    ///     Url
    /// </summary>
    public string Url { get; set; }

    /// <summary>
    ///     Referrer
    /// </summary>
    public string Referrer { get; set; }

    /// <summary>
    ///     IpAddress
    /// </summary>
    public string IpAddress { get; set; }

    /// <summary>
    ///     Milliseconds
    /// </summary>
    public int Milliseconds { get; set; }

    /// <summary>
    ///     QueryString
    /// </summary>
    public string QueryString { get; set; }

    /// <summary>
    ///     Request Body
    /// </summary>
    public string RequestBody { get; set; }

    /// <summary>
    ///     Cookies
    /// </summary>
    public string Cookies { get; set; }

    /// <summary>
    ///     Headers
    /// </summary>
    public string Headers { get; set; }

    /// <summary>
    ///     StatusCode
    /// </summary>
    public int StatusCode { get; set; }

    /// <summary>
    ///     Response Body
    /// </summary>
    public string ResponseBody { get; set; }

    public DateTime CreatedAt { get; set; } = DateTime.Now;
}